package com.springboot.seckill.service.impl;

import com.springboot.seckill.dataobject.OrderDO;
import com.springboot.seckill.dataobject.SequenceDO;
import com.springboot.seckill.enums.EmPromoConstants;
import com.springboot.seckill.error.BusinessException;
import com.springboot.seckill.error.EmBusinessError;
import com.springboot.seckill.mapper.OrderDOMapper;
import com.springboot.seckill.mapper.SequenceDOMapper;
import com.springboot.seckill.service.ItemService;
import com.springboot.seckill.service.OrderService;
import com.springboot.seckill.service.UserService;
import com.springboot.seckill.service.model.ItemModel;
import com.springboot.seckill.service.model.OrderModel;
import com.springboot.seckill.service.model.UserModel;
import com.springboot.seckill.utils.TimeUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

/**
 * @Author: HuangDekai
 * @Date: 2022/3/25 11:33
 * @Version: 1.0
 * @since: jdk11
 */
@Service
public class OrderServiceImpl implements OrderService {

    /**
     * 最大商品购买量
     */
    private static final Integer MAX_ITEM_AMOUNT = 99;
    /**
     * 自增序列位数
     */
    private static final Integer AUTO_INCREMENT_SEQUENCE_DIGIT = 8;

    @Autowired
    private ItemService itemService;
    @Autowired
    private UserService userService;

    @Autowired
    private OrderDOMapper OrderDOMapper;
    @Autowired
    private SequenceDOMapper sequenceDOMapper;

    /**
     * 创建订单
     *
     * @param userId 用户id
     * @param itemId 商品id
     * @param promoId 活动id
     * @param amount 购买的商品数
     * @return OrderModel
     * @throws BusinessException 用户不存在/商品不存在/数量不对
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    public OrderModel createOrder(Integer userId, Integer itemId, Integer promoId,Integer amount) throws BusinessException {
        // 1.校验下单状态,  下单商品是否存在, 用户是否合法, 购买数量是否正确
        ItemModel itemModel = itemService.getItemById(itemId);
        if (itemModel == null) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "商品信息不存在");
        }
        UserModel userModel = userService.getUserById(userId);
        if (userModel == null) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "用户信息不存在");
        }
        if (amount <= 0 || amount > MAX_ITEM_AMOUNT) {
            throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "商品数量不能小于等于0或大于"+MAX_ITEM_AMOUNT);
        }

        //校验活动信息
        if (promoId != null){
            //(1)校验对应活动是否存在这个适用商品
            if (promoId.intValue() != itemModel.getPromoModel().getId()) {
                throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "活动信息不正确");
            }
            //(2)校验活动是否正在进行
            else if (itemModel.getPromoModel().getStatus().intValue() != EmPromoConstants.SECKILL_STATUS_UNDERWAY.getValue()) {
                throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR, "活动不在进行中");
            }
        }

        // 2.落单减库存   (落单减库存(锁定给订单使用, 不会超卖), 支付减库存(落单看库存不锁, 返回可以下单, 支付时候再扣除(可以超卖)))
        boolean result = itemService.decreaseStock(itemId, amount);
        if (!result) {
            throw new BusinessException(EmBusinessError.STOCK_NOT_ENOUGH);
        }

        // 3.订单入库
        OrderModel orderModel = new OrderModel();
        orderModel.setUserId(userId);
        orderModel.setItemId(itemId);
        orderModel.setAmount(amount);
        if (promoId!=null) {
            orderModel.setItemPrice(itemModel.getPromoModel().getPromoItemPrice());
        } else {
            orderModel.setItemPrice(itemModel.getPrice());
        }
        orderModel.setPromoId(promoId);
        orderModel.setOrderPrice(itemModel.getPrice().multiply(new BigDecimal(amount)));

        // 生成交易流水号(订单号)
        orderModel.setOrderId(generateOrderNo());
        OrderDO orderDO = convertFromOrderModel(orderModel);
        OrderDOMapper.insertSelective(orderDO);

        // 加上商品的销量
        itemService.increaseSales(itemId, amount);
        // 4.返回前端
        return orderModel;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    String generateOrderNo() {
        //订单号24位
        StringBuilder stringBuilder = new StringBuilder();
        //前14位为时间信息 年月日时分秒
        String nowTimeString = TimeUtils.getNowTimeString();
        stringBuilder.append(nowTimeString);
        //中间8位为自增序列
        // "order_info"是sequence_info数据库里的name
        SequenceDO sequenceDO = sequenceDOMapper.getSequenceByName("order_info");
        Integer currentValue = sequenceDO.getCurrentValue();
        sequenceDO.setCurrentValue(sequenceDO.getCurrentValue() + sequenceDO.getStep());
        sequenceDOMapper.updateByPrimaryKeySelective(sequenceDO);

        String sequenceStr = String.valueOf(currentValue);
        //不足位数补0
        stringBuilder.append("0".repeat(Math.max(0, AUTO_INCREMENT_SEQUENCE_DIGIT - sequenceStr.length())));
        stringBuilder.append(sequenceStr);

        //最后2位为分库分表位(这里暂时不考虑, 先写死00)
        stringBuilder.append("00");
        return stringBuilder.toString();
    }

    /**
     * 将orderModel转换为oderDO
     * @param orderModel orderModel
     * @return orderDO
     */
    private OrderDO convertFromOrderModel(OrderModel orderModel) {
        if (orderModel == null) {
            return null;
        }
        OrderDO orderDO = new OrderDO();
        BeanUtils.copyProperties(orderModel, orderDO);

        return orderDO;
    }
}
